package JPLXtandemGA;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import com.mpb.prj.practice.JPLFDRCalculation;
import com.mpb.prj.practice.JPLGenerateXml;
import com.mpb.prj.practice.JPLMain;
import com.mpb.prj.practice.JPLRunXTandemBatchMain;

public class XTandemOps {

	/**
	 * TODO: Generate a random list of parameters
	 * 
	 * <note type="input"
	 * label="spectrum, fragment monoisotopic mass error">0.4</note> <note
	 * type="input"
	 * label="spectrum, parent monoisotopic mass error plus">10</note>
	 * type="input"
	 * label="spectrum, parent monoisotopic mass isotope error">yes</note> <note
	 * type="input" label="spectrum, minimum parent m+h">500.0</note> <note
	 * type="input" label="spectrum, minimum fragment mz">150.0</note> <note
	 * type="input" label="scoring, maximum missed cleavage sites">2</note>
	 * <note type="input" label="spectrum, total peaks">50</note> <note
	 * type="input" label="spectrum, maximum parent charge">4</note> <note
	 * type="input" label="spectrum, minimum peaks">15</note>
	 */
	public static List<IParameter> generate() {
		List<IParameter> lst = new ArrayList<IParameter>();
		IParameter massError = new DoubleParameter(
				"spectrum, fragment monoisotopic mass error", 0.4, 0, 1, 0.01);
		massError = massError.randomize();
		lst.add(massError); // (not working)
		
		IParameter isotopeError = new BooleanParameter(true,
				"spectrum,parent monoisotopic mass isotope error");
		isotopeError = isotopeError.randomize();
		lst.add(isotopeError);
		
		IParameter massErrorMinus = new IntegerParameter(
				"spectrum, parent monoisotopic mass error minus", 10, 1, 20);
		massErrorMinus = massErrorMinus.randomize();
		lst.add(massErrorMinus);
		
		IParameter maxParentChange = new IntegerParameter("spectrum, maximum parent charge",
				4, 1, 5);
		maxParentChange = maxParentChange.randomize();
		lst.add(maxParentChange);

		IParameter missedCleavage = new IntegerParameter(
				"scoring, maximum missed cleavage sites", 2, 1, 3);
		missedCleavage = missedCleavage.randomize();
		lst.add(missedCleavage);

		IParameter minParent = new DoubleParameter("spectrum, minimum parent m+h",
				500.0, 100, 2000, 100);
		minParent = minParent.randomize();
		lst.add(minParent);

		IParameter minFragment = new DoubleParameter("spectrum, minimum fragment mz",
				150.0, 0, 400, 50);
		minFragment = minFragment.randomize();
		lst.add(minFragment);

		IParameter minPeaks = new IntegerParameter("spectrum, minimum peaks", 15, 10,
				50);
		minPeaks = minPeaks.randomize();
//		lst.add(minPeaks);

		IParameter totalPeaks = new IntegerParameter("spectrum, total peaks", 50, 10,
				500);
		totalPeaks = totalPeaks.randomize();
//		lst.add(totalPeaks); // (not working)

		
		PeakParameters peakParams = new PeakParameters(totalPeaks, minPeaks);
		peakParams.validateAndFix();
		lst.add(peakParams);
		
		return lst;
	}

	/**
	 * 
	 * 
	 * @param x
	 * 
	 * @throws IOException
	 */
	public static void writeXMLFile(List<IParameter> list, String xmlFileName,
			String valuesFileName, boolean append) throws IOException {

		Iterator<IParameter> iterator = list.iterator();
		StringBuffer paramXml = new StringBuffer();
		StringBuffer inputValues = new StringBuffer();

		paramXml.append("<?xml version=\"1.0\"?>");
		paramXml.append("<?xml-stylesheet type=\"text/xsl\" href=\"tandem-input-style.xsl\"?>");
		paramXml.append("<bioml>");
		while (iterator.hasNext()) {
			IParameter tmp = iterator.next();
			paramXml.append(tmp.xmlRepresentation());
			inputValues.append(tmp.valueToString()).append(";");
		}
		inputValues.append("\n");
		inputValues.append("\n");
		paramXml.append("</bioml>");

		FileWriter fw = new FileWriter(new File(xmlFileName));
		fw.write(paramXml.toString());
		fw.flush();
		fw.close();

		FileWriter f = new FileWriter(new File(valuesFileName), append);
		f.write(inputValues.toString());
		f.flush();
		f.close();

		System.out.println(paramXml);
	}

	/**
	 * TODO: Evaluates an XML config file with XTandem and returns a score
	 * 
	 * @throws TransformerException
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public static double evaluate(String filename, Properties properties)
			throws SAXException, IOException, ParserConfigurationException,
			TransformerException {
		// I think you already implemented this
		JPLGenerateXml input = new JPLGenerateXml();
		input.setDataFolderPath(properties.getProperty("DATA_FOLDER"));
		input.setXtandemFolderPath(properties.getProperty("XTANDEM_FOLDER"));
		input.generateXtandemInputXml(properties.getProperty("TAXONOMY_FILE"),
				properties.getProperty("DEFAULT_INPUT_FILE"), properties
						.getProperty("SPECTRA_FILE"), filename);

		JPLRunXTandemBatchMain obj1 = new JPLRunXTandemBatchMain();
		obj1.runXTandem(properties.getProperty("XTANDEM_FOLDER"), properties
				.getProperty("DATA_FOLDER")
				+ "/new_input.xml", properties.getProperty("INPUT_FOLDER"),
				properties.getProperty("INPUT_REGEX"), properties
						.getProperty("OUTPUT_FOLDER"));

		JPLFDRCalculation outFile = new JPLFDRCalculation();
		return outFile.calculateFDR(properties.getProperty("OUTPUT_FOLDER"),
				properties.getProperty("OUTPUT_REGEX"),properties
				.getProperty("DATA_FOLDER")
				+ "/new_input.xml");
	}

	/**
	 * Allows to test that everything works together
	 * 
	 * @param properties
	 * @throws TransformerException
	 * @throws ParserConfigurationException
	 * @throws IOException
	 * @throws SAXException
	 */
	public static double evaluateRandomParameters(Properties properties,
			Boolean append) throws SAXException, IOException,
			ParserConfigurationException, TransformerException {
		String filename = "test.xml";
		String filename1 = "parameters.txt";

		List<IParameter> params = generate();
		
		try {
			writeXMLFile(params, filename, filename1, append);
		} catch (IOException e) {
			e.printStackTrace();
		}

		return evaluate(filename, properties);
	}

	public static void main(String args[]) throws FileNotFoundException,
			IOException, SAXException, ParserConfigurationException,
			TransformerException {
		Properties properties = new Properties();
		properties.load(new FileInputStream(args[0]));

		int loopTimes = 100;
		double fdrs[] = new double[loopTimes];
		for (int i = 0; i < loopTimes; i++) {
			System.out.println("Iteration.. " + i);
			if (i == 0) {
				fdrs[i] = evaluateRandomParameters(properties, false);
			} else {
				fdrs[i] = evaluateRandomParameters(properties, true);
			}
			System.out.println("fdrs[" + i + "] = " + fdrs[i]);
		}
		File file = new File("fdr_hist.txt");
		FileWriter fw = new FileWriter(file);
		for (int i = 0; i < loopTimes; i++) {
			fw.write(Double.toString(fdrs[i]) + "\n");
		}
		fw.flush();
		fw.close();
	}
}
